package com.zmn.plat.dubbo.impl.pic;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.zmn.common.dto.AliyunOssStsDTO;
import com.zmn.common.dto.ResponseDTO;
import com.zmn.common.dto.ResultDTO;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.plat.business.impl.pic.PicUploadBServiceImpl;
import com.zmn.plat.business.interfaces.pic.PicUploadBService;
import com.zmn.plat.dubbo.impl.PlatBaseRemoteServiceImpl;
import com.zmn.plat.dubbo.interfaces.pic.PicUploadRemoteService;
import com.zmn.plat.dubbo.utils.DubboConsts;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.dubbo.config.annotation.Service;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;

/**
 * @author duanzuocai
 * @version v1.0
 * @since 2018/11/20 15:55
 */
@Slf4j
@Service(loadbalance = "roundrobin", timeout = 5000, retries = -1, version = DubboConsts.INTERFACE_VERSION, validation = "true")
public class PicUploadRemoteServiceImpl extends PlatBaseRemoteServiceImpl implements PicUploadRemoteService {

    public static int PIC_UPLOAD_MAX_LENGTH = 3 * 1024 * 1024;

    @Value("${ali.yun.oss.pic.width}")
    Integer DEFAULT_WIDTH;
    @Value("${ali.yun.oss.pic.height}")
    Integer DEFAULT_HEIGHT;

    @Resource
    PicUploadBService picUploadBService;

    @Override
    public ResponseDTO uploadPic(String directory, String fileName, File file) {
        ResultDTO result;

        // 如果大小超过总大小，则使用默认压缩
        if (file.length() > PIC_UPLOAD_MAX_LENGTH) {
            result = picUploadBService.uploadPic(directory, fileName, file, DEFAULT_WIDTH, DEFAULT_HEIGHT);
        } else {
            result = picUploadBService.uploadPic(directory, fileName, file);
        }

        ResponseDTO dto = getResponseDTO(result);

        return dto;
    }

    @Override
    public ResponseDTO uploadPic(String directory, String fileName, File file, Integer maxWidth, Integer maxHeight) {
        ResultDTO result;

        if (!PicUploadBServiceImpl.hasValue(maxWidth, maxHeight)) {
            return uploadPic(directory, fileName, file);
        }

        result = picUploadBService.uploadPic(directory, fileName, file, maxWidth, maxHeight);

        ResponseDTO dto = getResponseDTO(result);

        return dto;
    }

    @Override
    public com.zmn.common.dto2.ResponseDTO<String> uploadPicLimiting(String directory, String fileName, String base64File, Integer maxWidth, Integer maxHeight) {

        String ipAddress = super.getIPAddress();
        String ip = StringUtil.isBlank(ipAddress) ? "0.0.0.0" : ipAddress;

        if (StringUtil.isBlank(base64File)) {
            return com.zmn.common.dto2.ResponseDTO.fail("上传的文件不能是null");
        }
        int startIndex = base64File.indexOf(",");
        base64File = base64File.substring(startIndex + 1);

        try (Entry entry = SphU.entry("Exception_Add_IP", EntryType.IN, 1, ip)) {
            byte[] bytes = Base64.decodeBase64(base64File);
            ResponseDTO responseDTO = this.uploadPic(directory, fileName, bytes, maxWidth, maxHeight);
            if (responseDTO.getStatusBool()) {
                String picUrl = getPicUrl(directory, fileName);
                return com.zmn.common.dto2.ResponseDTO.success(picUrl, "操作成功");
            } else {
                log.error("文件上传失败，msg:{}", responseDTO.getMessage());
                return com.zmn.common.dto2.ResponseDTO.fail("操作失败");
            }
        } catch (BlockException e) {
            log.error("{}IP限流{}", "上传文件", ip);
            return com.zmn.common.dto2.ResponseDTO.fail(ip + ": 限流");
        } catch (Exception e) {
            log.error("{}操作异常{}", "上传文件", e);
            return com.zmn.common.dto2.ResponseDTO.fail(ip + ": 操作异常");
        }
    }

    @Override
    public ResponseDTO uploadPic(String directory, String fileName, byte[] bytes) {
        InputStream inputStream = new ByteArrayInputStream(bytes);

        ResultDTO result = picUploadBService.uploadPic(directory, fileName, inputStream);

        ResponseDTO dto = getResponseDTO(result);

        return dto;
    }

    @Override
    public ResponseDTO uploadPic(String directory, String fileName, byte[] bytes, Integer maxWidth, Integer maxHeight) {
        InputStream inputStream = new ByteArrayInputStream(bytes);

        ResultDTO result = picUploadBService.uploadPic(directory, fileName, inputStream, maxWidth, maxHeight);

        ResponseDTO dto = getResponseDTO(result);

        return dto;
    }

    @Override
    public com.zmn.common.dto2.ResponseDTO<Boolean> uploadPicUnpressed(String directory, String fileName, InputStream inputStream) {

        ResultDTO result = picUploadBService.uploadPicUnpressed(directory, fileName, inputStream);

        if (result.getStatusBool()) {
            return com.zmn.common.dto2.ResponseDTO.success(true, "上传成功");
        } else {
            return com.zmn.common.dto2.ResponseDTO.fail(result.getMessage());
        }
    }

    @Override
    public com.zmn.common.dto2.ResponseDTO<Boolean> uploadPicUnpressed(String directory, String fileName, byte[] bytes) {

        InputStream inputStream = new ByteArrayInputStream(bytes);
        return this.uploadPicUnpressed(directory, fileName, inputStream);
    }

    @Override
    public com.zmn.common.dto2.ResponseDTO<Boolean> uploadPicUnpressedLimiting(String directory, String fileName, byte[] bytes) {

        String ip = super.getIPAddress();
        try (Entry entry = SphU.entry("Exception_Add_IP", EntryType.IN, 1, ip)) {
            return this.uploadPicUnpressed(directory, fileName, bytes);
        } catch (BlockException e) {
            log.error("{}IP限流{}", "上传文件", ip);
            return com.zmn.common.dto2.ResponseDTO.fail(ip + ": 限流");
        } catch (Exception e) {
            log.error("{}操作异常{}", "上传文件", e);
            return com.zmn.common.dto2.ResponseDTO.fail(ip + ": 操作异常");
        }
    }

    @NotNull
    private ResponseDTO getResponseDTO(ResultDTO result) {
        ResponseDTO dto = new ResponseDTO();
        dto.setStatusBool(result.getStatusBool());
        dto.setMessage(result.getMessage());
        return dto;
    }

    @Override
    public String getPicUrl(String directory, String fileName) {
        String result = picUploadBService.getPicUrl(directory, fileName);
        return result;
    }

    @Override
    @Cacheable(key = "'dubbo:pic:ali-sts:'+#p0", cacheNames = "redis1h")
    public AliyunOssStsDTO getStsAuther(String serviceId) {
        return picUploadBService.getStsAuther(serviceId);
    }
}
